﻿using BlueDot.Mobile.Core;
using System;
using SqlMergeReplication.Services;

namespace SqlMergeReplication.Controllers
{
    public class SyncController : ControllerBase
    {
        public const string SyncCompletedAction = "action://SqlMergeReplication/SyncCompleted";

        public void Synchronize()
        {
            this.StateBag[ApplicationStateBagItems.SYNC_STATUS].Value = string.Empty;
            IReplicationService replService = this.Application.GetService<IReplicationService>();    
            try
            {
                if (!replService.Initialized)
                {                    
                    replService.StatusChanged += new EventHandler<DataEventArgs<string>>(service_OnStatusUpdate);
                    replService.SynchronizationCompleted += new EventHandler(service_SynchronizationCompleted);
                    replService.Initialize(GetConfiguration());
                }
                replService.Execute();

            }
            catch (Exception ex)
            {
                SetStatusText(ex.ToString());
                CompleteSynchronization();
            }
        }

        private ReplicationConfiguration GetConfiguration()
        {
            IConfigurationService configService = this.Application.GetService<IConfigurationService>();
            IDeviceService deviceService = this.Application.GetService<IDeviceService>();
                   
            ReplicationConfiguration config = new ReplicationConfiguration();

            config.LocalDatabaseName = configService.GetValue(CommonConfigurationKeys.DB_CONN_STRING);
            config.InternetUrl = configService.GetValue(ReplicationConfigurationKeys.REPL_URL);
            config.InternetLogin = configService.GetValue(ReplicationConfigurationKeys.REPL_USER);
            config.InternetPassword = configService.GetValue(ReplicationConfigurationKeys.REPL_PWD);
            config.Publisher = configService.GetValue(ReplicationConfigurationKeys.REPL_PUB);
            config.PublisherDatabase = configService.GetValue(ReplicationConfigurationKeys.REPL_DB);
            config.Publications = configService.GetValue(ReplicationConfigurationKeys.REPL_PUBLICATIONS).Split(',');
            config.CreateSubscription = false;
            config.AuthenticationType = "NTAuthentication";
            config.FinishedSuccessMessage = "Replication completed successfully.";
            config.FinishedErrorMessage = "Replication completed but failed.";
            config.DeviceName = deviceService.GetDeviceId();

            config.HostName = "$(HostNameHere)";

            return config;            
        }

        void service_SynchronizationCompleted(object sender, EventArgs e)
        {
            CompleteSynchronization();
        }

        private void CompleteSynchronization()
        {
            InvokeOnUIThread(
               Application,
               () =>
               {
                   Application.Actions[SyncCompletedAction].Fire(this, EventArgs.Empty);
               });
        }

        void service_OnStatusUpdate(object sender, DataEventArgs<string> e)
        {
            SetStatusText(e.Data);
        }

        private void SetStatusText(string message)
        {
            InvokeOnUIThread(
                Application,
                () =>
                {
                    string messages = StateBag[ApplicationStateBagItems.SYNC_STATUS].Value as string;

                    StateBag[ApplicationStateBagItems.SYNC_STATUS].Value = string.Format(
                        "{0}{1}{2}",
                        message,
                        System.Environment.NewLine,
                        messages);
                });
        }

        public void InvokeOnUIThread(IMobileApplication application, System.Action action)
        {
            try
            {
                if (((Shell)this.Application.Shell).IsDisposed == false)
                {
                    this.Application.Shell.Invoke(action, new object[0]);
                }
            }
            catch (Exception)
            {
                //Do something
            }
        }
    }
}
